package com.codezj.utils;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import lombok.extern.slf4j.Slf4j;

/**
 * @Author: baozhongjie
 * @Version: v1.0.0
 * @Description: JSON工具类
 **/
@Slf4j
public class JsonUtil {

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    static {
        OBJECT_MAPPER.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
                .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
                .setSerializationInclusion(JsonInclude.Include.NON_NULL);// 序列化时，忽略值为null的属性

        OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
        OBJECT_MAPPER.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true);
    }


    public static <T> T parse(String content, Class<T> valueType) {
        try {
            return OBJECT_MAPPER.readValue(content, valueType);
        } catch (Exception e) {
            log.error("[ERROR] Json parse failed.", e);
            return null;
        }
    }

    public static JsonNode readTree(String content) {
        try {
            return OBJECT_MAPPER.readTree(content);
        } catch (Exception e) {
            log.error("[ERROR] Json parse tree failed. content:{} ",content, e);
            return null;
        }
    }

    public static String toJson(Object value) {
        try {
            // 当value为null时，Jackson会返回"null"字符串，不会抛出异常
            return OBJECT_MAPPER.writeValueAsString(value);
        } catch (Exception e) {
            log.error("[ERROR] toJson failed. ", e);
            return null;
        }
    }


    public static <T> T parse(String value, TypeReference<T> typeReference) {
        try {
            return OBJECT_MAPPER.readValue(value, typeReference);
        } catch (Exception e) {
            log.error("[ERROR] parse from json failed. ", e);
            return null;
        }
    }

    public static <T> T parse(String value, Class<?> container, Class<?>... actualType) {
        try {
            JavaType javaType = OBJECT_MAPPER.getTypeFactory().constructParametricType(container, actualType);
            return OBJECT_MAPPER.readValue(value, javaType);
        } catch (Exception e) {
            log.error("[ERROR] parse from json {} failed. ", value, e);
            return null;
        }
    }

    public static <T> T treeToValue(TreeNode node, Class<T> valueType) {
        try {
            return OBJECT_MAPPER.treeToValue(node, valueType);
        } catch (Exception e) {
            log.error("[ERROR] parse from json failed ", e);
            return null;
        }
    }


}
